package com.xzc.x86save.statementDesParser;

/**
 * 段描述符
 */
public class StatementDes {
    String baseAdd; //段基地址
    String limit; //段界限
    String G; //粒度-G
    String DB; //D/B位，D-代码段IP-EIP，B-栈段-SP-ESP
    String L; //64位标志
    String AVL; //备用位
    String P; //是否在物理内存中
    String DPL; //特权级-谁可以访问我，谁可以调用我
    String S; //是系统段，还是代码段或数据段
    String TYPE; //代码段XCRA,X-可执行，C-依从，R-可读，A-已使用，数据段XEWA，E-向上向下，W-可写

    String low;
    String hight;

    void parse(String bin) {
        decompose(bin);
        parseBaseAdd();
        parseLimit();
        parseG();
        parseDB();
        parseL();
        parseAVL();
        parseP();
        parseDPL();
        parseS();
        parseTYPE();
    }

    private void decompose(String bin) {
        hight = bin.substring(0, 8);
        low = bin.substring(8, 16);
    }

    private void parseBaseAdd() {
        byte[] binArrLow = BinUtil.parseHexStr2Byte(low);
        byte[] binArrHight = BinUtil.parseHexStr2Byte(hight);
        byte[] tmp = new byte[4];
        tmp[0] = binArrHight[0];
        tmp[1] = binArrHight[3];
        tmp[2] = binArrLow[0];
        tmp[3] = binArrLow[1];
        baseAdd = "0x" + BinUtil.parseByte2HexStr(tmp);
    }

    private void parseLimit() {
        byte[] binArrLow = BinUtil.parseHexStr2Byte(low);
        byte[] binArrHight = BinUtil.parseHexStr2Byte(hight);
        byte[] tmp = new byte[3];
        tmp[0] = binArrHight[1];
        tmp[1] = binArrLow[2];
        tmp[2] = binArrLow[3];
        tmp[0] = (byte) (tmp[0] & 0b00001111);
        limit = "0x" + BinUtil.parseByte2HexStr(tmp);
    }

    private void parseG() {
        byte[] binArrHight = BinUtil.parseHexStr2Byte(hight);
        String one = Integer.toBinaryString(binArrHight[1] & 0xFF);
        for (int i = 0; i < 8 - one.length(); i++) {
            one = "0" + one;
        }
        G = one.substring(0, 1);
    }

    private void parseDB() {
        byte[] binArrHight = BinUtil.parseHexStr2Byte(hight);
        String one = Integer.toBinaryString(binArrHight[1] & 0xFF);
        for (int i = 0; i < 8 - one.length(); i++) {
            one = "0" + one;
        }
        DB = one.substring(1, 2);
    }

    private void parseL() {
        byte[] binArrHight = BinUtil.parseHexStr2Byte(hight);
        String one = Integer.toBinaryString(binArrHight[1] & 0xFF);
        for (int i = 0; i < 8 - one.length(); i++) {
            one = "0" + one;
        }
        L = one.substring(2, 3);
    }

    private void parseAVL() {
        byte[] binArrHight = BinUtil.parseHexStr2Byte(hight);
        String one = Integer.toBinaryString(binArrHight[1] & 0xFF);
        for (int i = 0; i < 8 - one.length(); i++) {
            one = "0" + one;
        }
        AVL = one.substring(3, 4);
    }

    private void parseP() {
        byte[] binArrHight = BinUtil.parseHexStr2Byte(hight);
        String one = Integer.toBinaryString(binArrHight[2] & 0xFF);
        for (int i = 0; i < 8 - one.length(); i++) {
            one = "0" + one;
        }
        P = one.substring(0, 1);
    }

    private void parseDPL() {
        byte[] binArrHight = BinUtil.parseHexStr2Byte(hight);
        String one = Integer.toBinaryString(binArrHight[2] & 0xFF);
        for (int i = 0; i < 8 - one.length(); i++) {
            one = "0" + one;
        }
        DPL = one.substring(1, 3);
        int tmp = Integer.parseInt(DPL, 2);
        DPL = String.valueOf(tmp);
    }

    private void parseS() {
        byte[] binArrHight = BinUtil.parseHexStr2Byte(hight);
        String one = Integer.toBinaryString(binArrHight[2] & 0xFF);
        for (int i = 0; i < 8 - one.length(); i++) {
            one = "0" + one;
        }
        S = one.substring(3, 4);
    }

    private void parseTYPE() {
        byte[] binArrHight = BinUtil.parseHexStr2Byte(hight);
        String one = Integer.toBinaryString(binArrHight[2] & 0xFF);
        for (int i = 0; i < 8 - one.length(); i++) {
            one = "0" + one;
        }
        TYPE = one.substring(4, 8);
    }

    @Override
    public String toString() {
        return "StatementDes{" +
                "baseAdd='" + baseAdd + '\'' + "\n" +
                ", limit='" + limit + '\'' + "\n" +
                ", G='" + G + '\'' + "\n" +
                ", DB='" + DB + '\'' + "\n" +
                ", L='" + L + '\'' + "\n" +
                ", AVL='" + AVL + '\'' + "\n" +
                ", P='" + P + '\'' + "\n" +
                ", DPL='" + DPL + '\'' + "\n" +
                ", S='" + S + '\'' + "\n" +
                ", TYPE='" + TYPE + '\'' + "\n" +
                ", low='" + low + '\'' + "\n" +
                ", hight='" + hight + '\'' + "\n" +
                '}';
    }
}
